package com.mdata.service;

import com.mdata.common.*;
import com.mdata.model.dto.wechat.dto.DepartmentCreateDTO;
import com.mdata.model.dto.wechat.dto.DepartmentUpdateDTO;
import com.mdata.model.dto.wechat.dto.GroupChatGetListDTO;
import com.mdata.model.dto.wechat.result.*;
import com.mdata.model.vo.DepartmentSimpleVO;
import com.mdata.model.vo.DepartmentTreeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DepartmentService extends CommonService {

    @Autowired
    private SimpleService simpleService;
    @Autowired
    private GroupChatService groupChatService;

    /**
     * 部门Map<部门id， 部门名称>
     * @return
     */
    public Map<Integer, String> getDepartmentNameMap(@Nullable Integer id){
        List<Department> departmentList = getDepartmentList(id);
        return departmentList.stream().collect(Collectors.toMap(o -> o.getId(), o -> o.getName()));
    }

    /**
     * 请求方式：GET（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=ID
     *
     * 参数说明 ：
     * 参数 	必须 	说明
     * access_token 	是 	调用接口凭证
     * id 	否 	部门id。获取指定部门及其下的子部门（以及及子部门的子部门等等，递归）。 如果不填，默认获取全量组织架构
     * @return
     */
    public List<Department> getDepartmentList(@Nullable Integer id){
        MultiValueMap<String, String> queryParamMap = new LinkedMultiValueMap<>();
        if(Objects.nonNull(id)){
            queryParamMap.add("id", id.toString());
        }
        String url = splicingAccessToken(getWechatAddressBookSecret(), "department/list", queryParamMap);
        DepartmentListResult departmentListResult = BaseRestRequest.getForObject(restTemplate, url, DepartmentListResult.class);
        if(!Objects.equals(departmentListResult.getErrCode(), CommonCodeConstant.SUCCESS_CODE)){
            log.error(departmentListResult.getErrMsg());
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_GET_DEPARTMENT_LIST);
        }
       return departmentListResult.getDepartmentList();
    }

    /**
     * 获取部门 tree
     * @return
     */
    public List<DepartmentTreeVO> getDepartmentTree(){
        List<Department> departmentList = getDepartmentList(null);
        return departmentList.stream()
                .filter(o -> o.getParentId() == 0)
                .peek(o -> o.setChildrens(getChildDepartmentList(o, departmentList)))
                .sorted(Comparator.comparingInt(Department::getOrder))
                .map(o -> DepartmentTreeVO.fromDepartment(o)).collect(Collectors.toList());
    }

    private List<Department> getChildDepartmentList(Department department, List<Department> departmentList) {
        return departmentList.stream().filter(o -> o.getParentId().equals(department.getId()))
                .peek(o -> o.setChildrens(getChildDepartmentList(o, departmentList)))
                .sorted(Comparator.comparingInt(Department::getOrder)).collect(Collectors.toList());
    }

    /**
     * 获取部门以及人员 tree，部门（人数，群数）
     * @return
     */
    public List<DepartmentSimpleVO> getDepartmentSimpleTree(){
        List<Department> departmentList = getDepartmentList(null);

        // 默认 应该根目录 departmentId = 1
        List<UserList> simpleList = simpleService.getSimpleList(1, 0);

        Map<String, Integer> simpleGroupChatCountMap = simpleList.stream().map(o -> o.getUserId()).collect(Collectors.toMap(o -> o, o -> {
            GroupChatGetListDTO groupChatGetListDTO = new GroupChatGetListDTO(0, null, 1000, Collections.singletonList(o));
            List<GroupChatList> groupChatList = groupChatService.getGroupChatList(groupChatGetListDTO);
            return groupChatList.size();
        }));

        return departmentList.stream()
                .filter(o -> o.getParentId() == 0)
                .peek(o -> {
                    o.setChildrens(getChildDepartmentList(o, departmentList, simpleList));
                    o.setSimpleList(simpleList.stream().filter(simple ->
                            Arrays.stream(simple.getDepartment()).anyMatch(department -> Objects.equals(department, o.getId()))).collect(Collectors.toList()));
                }).sorted(Comparator.comparingInt(Department::getOrder))
                .map(o -> DepartmentSimpleVO.fromDepartment(o, simpleGroupChatCountMap)).collect(Collectors.toList());
    }

    private List<Department> getChildDepartmentList(Department departmentResult, List<Department> departmentList, List<UserList> simpleList) {
        return departmentList.stream().filter(o -> o.getParentId().equals(departmentResult.getId()))
                .peek(o -> {
                    o.setChildrens(getChildDepartmentList(o, departmentList, simpleList));
                    o.setSimpleList(simpleList.stream().filter(simple ->
                            Arrays.stream(simple.getDepartment()).anyMatch(department -> Objects.equals(department, o.getId()))).collect(Collectors.toList()));
                }).sorted(Comparator.comparingInt(Department::getOrder)).collect(Collectors.toList());
    }

    /**
     * 创建部门
     * 请求方式：POST（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/create?access_token=ACCESS_TOKEN
     * @return
     */
    public Integer createDepartment(DepartmentCreateDTO departmentCreateDTO){
        String url = splicingAccessToken(getWechatAddressBookSecret(), "department/create");
        DepartmentCreateResult departmentCreateResult = BaseRestRequest.postForObject(restTemplate, url, departmentCreateDTO, DepartmentCreateResult.class);
        if(!Objects.equals(departmentCreateResult.getErrCode(), CommonCodeConstant.SUCCESS_CODE)){
            log.error(departmentCreateResult.getErrMsg());
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_CREATE_DEPARTMENT);
        }
        return departmentCreateResult.getId();
    }

    /**
     * 更新部门
     *
     * 请求方式：POST（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/update?access_token=ACCESS_TOKEN
     * @return
     */
    public WeChatBaseResult updateDepartment(DepartmentUpdateDTO departmentUpdateDTO){
        String url = splicingAccessToken(getWechatAddressBookSecret(), "department/update");
        WeChatBaseResult weChatBaseResult = BaseRestRequest.postForObject(restTemplate, url, departmentUpdateDTO, DepartmentCreateResult.class);
        if(!Objects.equals(weChatBaseResult.getErrCode(), CommonCodeConstant.SUCCESS_CODE)){
            log.error(weChatBaseResult.getErrMsg());
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_CREATE_DEPARTMENT);
        }
        return weChatBaseResult;
    }

    /**
     * 删除部门
     *
     * 请求方式：GET（HTTPS）
     * 请求地址：https://qyapi.weixin.qq.com/cgi-bin/department/delete?access_token=ACCESS_TOKEN&id=ID
     *
     * id 	是 	部门id。（注：不能删除根部门；不能删除含有子部门、成员的部门）
     * @return
     */
    public WeChatBaseResult deleteDepartment(Integer id){
        // 判断是否有子部门
        List<Department> departmentList = getDepartmentList(id);
        if(departmentList.stream().anyMatch(o -> !Objects.equals(o.getId(), id))){
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_DELETE_DEPARTMENT.getCode(), "不允许删除有子部门的部门！");
        }
        // 判断是否有成员
        List<UserList> simpleList = simpleService.getSimpleList(id, 0);
        if(!CollectionUtils.isEmpty(simpleList)){
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_DELETE_DEPARTMENT.getCode(), "不允许删除有成员的部门！");
        }
        MultiValueMap<String, String> queryParamMap = new LinkedMultiValueMap<>();
        queryParamMap.add("id", id.toString());
        String url = splicingAccessToken(getWechatAddressBookSecret(), "department/delete", queryParamMap);
        WeChatBaseResult weChatBaseResult = BaseRestRequest.postForObject(restTemplate, url, DepartmentCreateResult.class);
        if(!Objects.equals(weChatBaseResult.getErrCode(), CommonCodeConstant.SUCCESS_CODE)){
            log.error(weChatBaseResult.getErrMsg());
            throw new DefinitionException(ResponseEnum.WECHAT_ERROR_DELETE_DEPARTMENT);
        }
        return weChatBaseResult;
    }
}
